namespace Plugins.Xml.Serialization
{
    using System;

    public abstract class XmlRuntimeSerializer<T> : XmlRuntimeSerializer, IXmlRuntimeSerializer<T>
    {
        public override Type RuntimeType { get { return typeof(T); } }
        public override void Serialize(object value, IXmlPropertyWriter writer, string propertyName)
        {
            ((IXmlRuntimeSerializer<T>)this).Serialize((T)value, writer, propertyName);
        }
        public override void Serialize(object value, IXmlPropertyWriter writer, int index)
        {
            ((IXmlRuntimeSerializer<T>)this).Serialize((T)value, writer, index);
        }
        public override object Deserialize(IXmlPropertyReader reader, string propertyName)
        {
            return ((IXmlRuntimeSerializer<T>)this).Deserialize(reader, propertyName);
        }
        public override object Deserialize(IXmlPropertyReader reader, int index)
        {
            return ((IXmlRuntimeSerializer<T>)this).Deserialize(reader, index);
        }

        protected abstract void Write(T value, IXmlPropertyWriter writer, string propertyName);
        protected abstract void Write(T value, IXmlPropertyWriter writer, int index);
        protected abstract T Read(IXmlPropertyReader reader, string propertyName);
        protected abstract T Read(IXmlPropertyReader reader, int index);

        #region IXmlRuntimeSerializer<T> Members

        T IXmlRuntimeSerializer<T>.Deserialize(IXmlPropertyReader reader, string propertyName)
        {
            return Read(reader, propertyName);
        }
        T IXmlRuntimeSerializer<T>.Deserialize(IXmlPropertyReader reader, int index)
        {
            return Read(reader, index);
        }

        void IXmlRuntimeSerializer<T>.Serialize(T value, IXmlPropertyWriter writer, string propertyName)
        {
            Write(value, writer, propertyName);
        }
        void IXmlRuntimeSerializer<T>.Serialize(T value, IXmlPropertyWriter writer, int index)
        {
            Write(value, writer, index);
        }

        #endregion
    }
    public abstract class XmlRuntimeSerializer
    {
        private IXmlTypeSerializer<object> _enumSerializer;

        public XmlRuntimeSerializer() { _enumSerializer = new EnumSerializer(RuntimeType); }
        public IXmlTypeSerializer<bool> Boolean { get { return BooleanSerializer.Instance; } }
        public IXmlTypeSerializer<byte> Byte { get { return ByteSerializer.Instance; } }
        public IXmlTypeSerializer<Int16> Int16 { get { return Int16Serializer.Instance; } }
        public IXmlTypeSerializer<int> Int32 { get { return Int32Serializer.Instance; } }
        public IXmlTypeSerializer<Int64> Int64 { get { return Int64Serializer.Instance; } }
        public IXmlTypeSerializer<float> Float { get { return FloatSerializer.Instance; } }
        public IXmlTypeSerializer<double> Double { get { return DoubleSerializer.Instance; } }
        public IXmlTypeSerializer<Decimal> Decimal { get { return DecimalSerializer.Instance; } }
        public IXmlTypeSerializer<string> String { get { return StringSerializer.Instance; } }
        public IXmlTypeSerializer<object> Enum { get { return _enumSerializer; } }

        public abstract Type RuntimeType { get; }

        public abstract void Serialize(object value, IXmlPropertyWriter writer, string propertyName);
        public abstract void Serialize(object value, IXmlPropertyWriter writer, int index);

        public abstract object Deserialize(IXmlPropertyReader reader, string propertyName);
        public abstract object Deserialize(IXmlPropertyReader reader, int index);
    }
}
